1 package net.sourceforge.simplegamenet.chess;
2
3 import java.io.Serializable;
4
5 public class ChessPlayField implements ChessGridSize, ChessPlayFieldState, ChessPieceType,
6 ChessPieceOwner, Serializable {
7
8 public static final int[][] DEFAULT_PIECE_TYPE_GRID = {
9 {ROOK, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, ROOK},
10 {KNIGHT, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, KNIGHT},
11 {BISHOP, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, BISHOP},
12 {QUEEN, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, QUEEN},
13 {KING, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, KING},
14 {BISHOP, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, BISHOP},
15 {KNIGHT, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, KNIGHT},
16 {ROOK, PAWN, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, PAWN, ROOK}
17 };
18 public static final int[][] DEFAULT_PIECE_OWNER_GRID = {
19 {
20 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
21 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
22 },
23 {
24 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
25 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
26 },
27 {
28 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
29 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
30 },
31 {
32 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
33 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
34 },
35 {
36 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
37 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
38 },
39 {
40 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
41 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
42 },
43 {
44 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
45 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
46 },
47 {
48 BLACK_OWNER, BLACK_OWNER, NO_OWNER, NO_OWNER,
49 NO_OWNER, NO_OWNER, WHITE_OWNER, WHITE_OWNER
50 }
51 };
52
53 public static boolean isCheckState(ChessPiece[] checkingPieceGrid,
54 int participantsOwnerIndex) {
55 int kingX = -1;
56 int kingY = -1;
57 for (int i = 0; i < checkingPieceGrid.length; i++) {
58 if (checkingPieceGrid[i] != null && checkingPieceGrid[i] instanceof ChessKing
59 && checkingPieceGrid[i].getParticipantsOwnerIndex()
60 == participantsOwnerIndex) {
61 kingX = checkingPieceGrid[i].getX();
62 kingY = checkingPieceGrid[i].getY();
63 break;
64 }
65 }
66 for (int i = 0; i < GRID_HEIGHT * GRID_WIDTH; i++) {
67 if (checkingPieceGrid[i] != null
68 && checkingPieceGrid[i].getParticipantsOwnerIndex() != participantsOwnerIndex
69 && checkingPieceGrid[i].isMoveAllowed(checkingPieceGrid, kingX, kingY)) {
70 return true;
71 }
72 }
73 return false;
74 }
75
76 public static boolean isCheckAfterMoveState(ChessPiece[] checkingPieceGrid,
77 int participantsOwnerIndex) {
78 for (int i = 0; i < checkingPieceGrid.length; i++) {
79 if (checkingPieceGrid[i] != null
80 && checkingPieceGrid[i].getParticipantsOwnerIndex()
81 == participantsOwnerIndex) {
82 for (int j = 0; j < checkingPieceGrid.length; j++) {
83 if (checkingPieceGrid[i].isMoveAllowed(checkingPieceGrid,
84 j / GRID_HEIGHT, j % GRID_HEIGHT)) {
85 ChessPiece[] tempPieceGrid = new ChessPiece[checkingPieceGrid.length];
86 for (int k = 0; k < tempPieceGrid.length; k++) {
87 if (checkingPieceGrid[k] != null) {
88 tempPieceGrid[k] = (ChessPiece) checkingPieceGrid[k].clone();
89 }
90 }
91 tempPieceGrid[i].doMove(tempPieceGrid,
92 j / GRID_HEIGHT, j % GRID_HEIGHT);
93 if (!isCheckState(tempPieceGrid, participantsOwnerIndex)) {
94 return false;
95 }
96 }
97 }
98 }
99 }
100 return true;
101 }
102
103 private Integer[] participantsOrder;
104
105 private int state = NORMAL_STATE;
106 private boolean waitingForRemiseOfferAnswer = false;
107
108 private int participantAtTurnIndex = 0;
109
110 private ChessPiece[] pieceGrid = new ChessPiece[GRID_WIDTH * GRID_HEIGHT];
111
112 public ChessPlayField(Integer[] participantsOrder) {
113 this.participantsOrder = participantsOrder;
114 for (int i = 0; i < GRID_WIDTH; i++) {
115 for (int j = 0; j < GRID_HEIGHT; j++) {
116 ChessPiece chessPiece = null;
117 int participantOwnerIndex = -1;
118 switch (DEFAULT_PIECE_OWNER_GRID[i][j]) {
119 case WHITE_OWNER:
120 participantOwnerIndex = 0;
121 break;
122 case BLACK_OWNER:
123 participantOwnerIndex = 1;
124 break;
125 }
126 switch (DEFAULT_PIECE_TYPE_GRID[i][j]) {
127 case KING:
128 chessPiece = new ChessKing(participantOwnerIndex, i, j);
129 break;
130 case QUEEN:
131 chessPiece = new ChessQueen(participantOwnerIndex, i, j);
132 break;
133 case BISHOP:
134 chessPiece = new ChessBishop(participantOwnerIndex, i, j);
135 break;
136 case KNIGHT:
137 chessPiece = new ChessKnight(participantOwnerIndex, i, j);
138 break;
139 case ROOK:
140 chessPiece = new ChessRook(participantOwnerIndex, i, j);
141 break;
142 case PAWN:
143 chessPiece = new ChessPawn(participantOwnerIndex, i, j);
144 break;
145 }
146 pieceGrid[i * GRID_HEIGHT + j] = chessPiece;
147 }
148 }
149 }
150
151 public Integer getParticipantAtTurnPlayerID() {
152 return participantsOrder[participantAtTurnIndex];
153 }
154
155 public boolean isMoveAllowed(int sourceX, int sourceY,
156 int destinationX, int destinationY, int chosenPieceType) {
157 if (sourceX < 0 || sourceY < 0 || destinationX < 0 || destinationY < 0
158 || sourceX >= GRID_WIDTH || sourceY >= GRID_HEIGHT
159 || destinationX >= GRID_WIDTH || destinationY >= GRID_HEIGHT) {
160 return false;
161 }
162 if (isMoveAllowed(sourceX, sourceY, destinationX, destinationY)) {
163 if (isReplaceChoiceNeeded(sourceX, sourceY, destinationX, destinationY)) {
164 switch (chosenPieceType) {
165 case QUEEN:
166 return true;
167 case BISHOP:
168 return true;
169 case KNIGHT:
170 return true;
171 case ROOK:
172 return true;
173 default:
174 return false;
175 }
176 } else {
177 return true;
178 }
179 } else {
180 return false;
181 }
182 }
183
184 private boolean isMoveAllowed(int sourceX, int sourceY,
185 int destinationX, int destinationY) {
186 if (pieceGrid[sourceX * GRID_HEIGHT + sourceY] == null) {
187 return false;
188 }
189 if (pieceGrid[sourceX * GRID_HEIGHT + sourceY]
190 .isMoveAllowed(pieceGrid, destinationX, destinationY)) {
191 ChessPiece[] tempPieceGrid = new ChessPiece[pieceGrid.length];
192 for (int i = 0; i < tempPieceGrid.length; i++) {
193 if (pieceGrid[i] != null) {
194 tempPieceGrid[i] = (ChessPiece) pieceGrid[i].clone();
195 }
196 }
197 tempPieceGrid[sourceX * GRID_HEIGHT + sourceY]
198 .doMove(tempPieceGrid, destinationX, destinationY);
199 return !isCheckState(tempPieceGrid,
200 tempPieceGrid[destinationX * GRID_HEIGHT + destinationY]
201 .getParticipantsOwnerIndex());
202 } else {
203 return false;
204 }
205 }
206
207 public int doMove(int sourceX, int sourceY, int destinationX, int destinationY,
208 int chosenPieceType) {
209 if (isReplaceChoiceNeeded(sourceX, sourceY, destinationX, destinationY)) {
210 pieceGrid[sourceX * GRID_HEIGHT + sourceY].doMove(pieceGrid,
211 destinationX, destinationY);
212 switch (chosenPieceType) {
213 case QUEEN:
214 pieceGrid[destinationX * GRID_HEIGHT + destinationY]
215 = new ChessQueen(pieceGrid[destinationX * GRID_HEIGHT + destinationY]
216 .getParticipantsOwnerIndex(),
217 destinationX, destinationY);
218 break;
219 case BISHOP:
220 pieceGrid[destinationX * GRID_HEIGHT + destinationY]
221 = new ChessBishop(pieceGrid[destinationX * GRID_HEIGHT + destinationY]
222 .getParticipantsOwnerIndex(),
223 destinationX, destinationY);
224 break;
225 case KNIGHT:
226 pieceGrid[destinationX * GRID_HEIGHT + destinationY]
227 = new ChessKnight(pieceGrid[destinationX * GRID_HEIGHT + destinationY]
228 .getParticipantsOwnerIndex(),
229 destinationX, destinationY);
230 break;
231 case ROOK:
232 pieceGrid[destinationX * GRID_HEIGHT + destinationY]
233 = new ChessRook(pieceGrid[destinationX * GRID_HEIGHT + destinationY]
234 .getParticipantsOwnerIndex(),
235 destinationX, destinationY);
236 break;
237 }
238 } else {
239 pieceGrid[sourceX * GRID_HEIGHT + sourceY].doMove(pieceGrid,
240 destinationX, destinationY);
241 }
242 participantAtTurnIndex = (participantAtTurnIndex + 1) % participantsOrder.length;
243 if (isCheckState(pieceGrid, participantAtTurnIndex)) {
244 if (isCheckAfterMoveState(pieceGrid, participantAtTurnIndex)) {
245 state = CHECKMATE;
246 participantAtTurnIndex = (participantAtTurnIndex + 1)
247 % participantsOrder.length;
248 } else {
249 state = CHECK;
250 }
251 } else {
252 if (isCheckAfterMoveState(pieceGrid, participantAtTurnIndex)) {
253 state = STALEMATE;
254 participantAtTurnIndex = -1;
255 } else {
256 state = NORMAL_STATE;
257 }
258 }
259 return state;
260 }
261
262 public void setWaitingForRemiseOfferAnswer() {
263 waitingForRemiseOfferAnswer = true;
264 }
265
266 public int setRemiseOfferAnswer(boolean remiseOfferAccepted) {
267 waitingForRemiseOfferAnswer = false;
268 if (remiseOfferAccepted) {
269 state = REMISE;
270 participantAtTurnIndex = -1;
271 }
272 return state;
273 }
274
275 public int yieldGame(Integer playerID) {
276 int participantsIndex = 0;
277 for (int i = 0; i < participantsOrder.length; i++) {
278 if (participantsOrder[i].equals(playerID)) {
279 participantsIndex = i;
280 break;
281 }
282 }
283 state = YIELDED;
284 participantAtTurnIndex = (participantsIndex + 1) % participantsOrder.length;
285 return state;
286 }
287
288 public boolean[][] getMoveSourceAllowedGrid() {
289 boolean[][] moveSourceAllowedGrid = new boolean[GRID_WIDTH][GRID_HEIGHT];
290 for (int i = 0; i < GRID_WIDTH; i++) {
291 for (int j = 0; j < GRID_HEIGHT; j++) {
292 moveSourceAllowedGrid[i][j] = pieceGrid[i * GRID_HEIGHT + j] != null
293 && pieceGrid[i * GRID_HEIGHT + j]
294 .getParticipantsOwnerIndex()
295 == participantAtTurnIndex;
296 }
297 }
298 return moveSourceAllowedGrid;
299 }
300
301 public boolean[][] getMoveDestinationAllowedGrid(int sourceX, int sourceY) {
302 boolean[][] moveDestinationAllowedGrid = new boolean[GRID_WIDTH][GRID_HEIGHT];
303 for (int i = 0; i < GRID_HEIGHT; i++) {
304 for (int j = 0; j < GRID_WIDTH; j++) {
305 moveDestinationAllowedGrid[i][j] = isMoveAllowed(sourceX, sourceY, i, j);
306 }
307 }
308 return moveDestinationAllowedGrid;
309 }
310
311 public boolean isReplaceChoiceNeeded(int sourceX, int sourceY,
312 int destinationX, int destinationY) {
313 return pieceGrid[sourceX * GRID_HEIGHT + sourceY] != null
314 && pieceGrid[sourceX * GRID_HEIGHT + sourceY] instanceof ChessPawn
315 && ((ChessPawn) pieceGrid[sourceX * GRID_HEIGHT + sourceY])
316 .isReplaceChoiceNeeded(destinationX, destinationY);
317 }
318
319 public int getPieceOwnerSight(Integer clientPlayerID) {
320 if (clientPlayerID.equals(participantsOrder[0])) {
321 return WHITE_OWNER;
322 } else if (clientPlayerID.equals(participantsOrder[1])) {
323 return BLACK_OWNER;
324 }
325 return NO_OWNER;
326 }
327
328 public int getPlayFieldState() {
329 return state;
330 }
331
332 public int[][] getPieceTypeGrid() {
333 int[][] pieceTypeGrid = new int[GRID_WIDTH][GRID_HEIGHT];
334 for (int i = 0; i < GRID_WIDTH; i++) {
335 for (int j = 0; j < GRID_HEIGHT; j++) {
336 if (pieceGrid[i * GRID_HEIGHT + j] == null) {
337 pieceTypeGrid[i][j] = NO_TYPE;
338 } else {
339 pieceTypeGrid[i][j] = pieceGrid[i * GRID_HEIGHT + j].getPieceType();
340 }
341 }
342 }
343 return pieceTypeGrid;
344 }
345
346 public int[][] getPieceOwnerGrid() {
347 int[][] pieceOwnerGrid = new int[GRID_WIDTH][GRID_HEIGHT];
348 for (int i = 0; i < GRID_WIDTH; i++) {
349 for (int j = 0; j < GRID_HEIGHT; j++) {
350 if (pieceGrid[i * GRID_HEIGHT + j] == null) {
351 pieceOwnerGrid[i][j] = NO_OWNER;
352 } else {
353 switch (pieceGrid[i * GRID_HEIGHT + j].getParticipantsOwnerIndex()) {
354 case 0:
355 pieceOwnerGrid[i][j] = WHITE_OWNER;
356 break;
357 case 1:
358 pieceOwnerGrid[i][j] = BLACK_OWNER;
359 break;
360 default:
361 pieceOwnerGrid[i][j] = NO_OWNER;
362 break;
363 }
364 }
365 }
366 }
367 return pieceOwnerGrid;
368 }
369
370 public int getState() {
371 return state;
372 }
373
374 public ChessPiece[] getPieceGrid() {
375 return pieceGrid;
376 }
377
378 }